<?php

namespace App\Models\Cruise;

use App\Models\BaseModel;
use App\Models\Traits\KfSoftDeletes;
use App\Models\Traits\KfUid;
use App\Service\BaseService;
use Carbon\Carbon;
use DateInterval;
use DateTime;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;

class CruiseCheckSelfTaskModel extends BaseModel
{
    use KfUid, KfSoftDeletes;

    protected $table    = 'cruise_check_self_task';
    protected $fillable = [
        'templateType',
        'name',
        'rule',
        'taskStartTime',
        'taskEndTime',
        'executeStartHis',
        'executeEndHis',
        'templateId',
        'status',
        'shopScope',
        'isDeleted',
    ];


    const RULE_DAY   = 1;
    const RULE_WEEK  = 2;
    const RULE_MONTH = 3;

    const RULE_TEXT = [
        self::RULE_DAY   => '每日一检',
        self::RULE_WEEK  => '每周一检',
        self::RULE_MONTH => '每月一检',
    ];

    const STATUS_OFF = 0;
    const STATUS_ON  = 1;

    const STATUS_TEXT = [
        self::STATUS_OFF => '停用',
        self::STATUS_ON  => '启用',
    ];

    /**
     * 门店自检状态
     */
    const TYPE_8_STATE_0    = 0;
    const TYPE_8_STATE_1    = 1;
    const TYPE_8_STATE_2    = 2;
    const TYPE_8_STATE_3    = 3;
    const TYPE_8_STATE_TEXT = [
        self::TYPE_8_STATE_0 => "全部",
        self::TYPE_8_STATE_1 => "进行中",
        self::TYPE_8_STATE_2 => "未开始",
        self::TYPE_8_STATE_3 => "已完成",
    ];

    const SHOP_SCOPE_ALL  = 1; // 全部门店
    const SHOP_SCOPE_PART = 0; // 部分门店
    const SHOP_SCOPE_TEXT = [
        self::SHOP_SCOPE_PART => "部分门店",
        self::SHOP_SCOPE_ALL  => "全部门店",
    ];

    const EXECUTE_TYPE_CUSTOM = 0;
    const EXECUTE_TYPE_SHOP   = 1;
    const EXECUTE_TYPE_TEXT   = [
        self::EXECUTE_TYPE_CUSTOM => "自定义时间",
        self::EXECUTE_TYPE_SHOP   => "门店营业时间",
    ];

    /**
     * @return HasOne
     */
    public function cruiseTemplateRel(): HasOne
    {
        return $this->hasOne(CruiseTemplateModel::class, "id", "templateId");
    }

    /**
     * @return HasMany
     */
    public function cruiseCheckSelfTaskCompanyMappingsRel(): HasMany
    {
        return $this->hasMany(CruiseCheckSelfTaskCompanyMappingModel::class, "taskId", "id");
    }

    /**
     * @return HasMany
     */
    public function cruiseCheckSelfDetailRel(): HasMany
    {
        return $this->hasMany(CruiseCheckSelfDetailModel::class, "taskId", "id");
    }

    /**
     * 获取状态
     *
     * @param CruiseCheckSelfTaskModel $checkSelfTaskModel
     * @return array|void
     */
    public static function transStatus(CruiseCheckSelfTaskModel $checkSelfTaskModel)
    {
        if ($checkSelfTaskModel->status == self::STATUS_OFF) {
            return [self::TYPE_8_STATE_3, "已结束"];
        }

        if ($checkSelfTaskModel->taskStartTime > time()) {
            return [self::TYPE_8_STATE_2, "未开始"];
        }

        if ($checkSelfTaskModel->taskEndTime < time()) {
            return [self::TYPE_8_STATE_3, "已结束"];
        }

        if ($checkSelfTaskModel->taskEndTime > time() && $checkSelfTaskModel->taskStartTime < time()) {
            return [self::TYPE_8_STATE_1, "进行中"];
        }
    }

    public function getRuleCycle(): array
    {
        switch ($this->rule) {
            case CruiseCheckSelfTaskModel::RULE_DAY:
                $ruleCycleStart = Carbon::now()->startOfDay()->timestamp;
                $ruleCycleEnd   = Carbon::now()->endOfDay()->timestamp;
                break;
            case CruiseCheckSelfTaskModel::RULE_WEEK:
                $ruleCycleStart = Carbon::now()->startOfWeek()->timestamp;
                $ruleCycleEnd   = Carbon::now()->endOfWeek()->timestamp;
                break;
            case CruiseCheckSelfTaskModel::RULE_MONTH:
                $ruleCycleStart = Carbon::now()->startOfMonth()->timestamp;
                $ruleCycleEnd   = Carbon::now()->endOfMonth()->timestamp;
                break;
            default:
                BaseService::throwErr('当前规则暂无法解析 [ ruleType : ' . $this->rule . ']');
        }

        return [$ruleCycleStart, $ruleCycleEnd];
    }

    /**
     * 获取执行周期
     *
     * @param CruiseCheckSelfTaskModel $checkSelfTaskModel
     * @param int $createdTime
     * @return array
     * @throws Exception
     */
    public static function getExecuteRuleCycle(CruiseCheckSelfTaskModel $checkSelfTaskModel, int $createdTime): array
    {
        switch ($checkSelfTaskModel->rule) {
            case CruiseCheckSelfTaskModel::RULE_DAY:
                $startDatetime  = new DateTime($checkSelfTaskModel->executeStartHis);
                $endDatetime    = new DateTime($checkSelfTaskModel->executeEndHis);
                $startTimestamp = strtotime(date("Y-m-d", $createdTime) . " {$checkSelfTaskModel->executeStartHis}");
                if ($startDatetime >  $endDatetime) {
                    // todo 跨天
                    $endTimestamp = strtotime(
                            date("Y-m-d", $createdTime) . " {$checkSelfTaskModel->executeEndHis}"
                        ) + 86400;
                } else {
                    $endTimestamp = strtotime(date("Y-m-d", $createdTime) . " {$checkSelfTaskModel->executeEndHis}");
                }
                break;
            case CruiseCheckSelfTaskModel::RULE_WEEK:
                $baseDate       = Carbon::createFromTimestamp($createdTime);
                $startTimestamp = (clone $baseDate)->startOfWeek()->timestamp;
                $endTimestamp   = $checkSelfTaskModel->taskEndTime > (clone $baseDate)->endOfWeek()->timestamp ?
                    (clone $baseDate)->endOfWeek()->timestamp : $checkSelfTaskModel->taskEndTime;
                break;
            case CruiseCheckSelfTaskModel::RULE_MONTH:
                $baseDate       = Carbon::createFromTimestamp($createdTime);
                $startTimestamp = (clone $baseDate)->startOfMonth()->timestamp;
                $endTimestamp   = $checkSelfTaskModel->taskEndTime > (clone $baseDate)->endOfMonth()->timestamp ?
                    (clone $baseDate)->endOfMonth()->timestamp : $checkSelfTaskModel->taskEndTime;
                break;
            default:
                throw new Exception('当前规则暂无法解析 [ ruleType : ' . $checkSelfTaskModel->rule . ']');
        }

        return [$startTimestamp, $endTimestamp];
    }


}
